// @ts-check
const fs = require('fs')
const { resolve } = require('path')
const os = require("os")
const express = require('express')
const port = process.env.port || process.env.npm_config_port || process.env.NODE_ENV === 'dev' ? 3000  : 9097// 端口

const JSONFILE = './local.bak.json';
const MSG = {
  success: {
    code: '0',
    message: 'success'
  }
}

async function createServer(
  root = process.cwd(),
  isProd = process.env.NODE_ENV === 'production'
) {
 
  const indexProd = isProd
    ? fs.readFileSync(resolve('dist/client/index.html'), 'utf-8')
    : ''

  const manifest = isProd
    ? // @ts-ignore
      require('./dist/client/ssr-manifest.json')
    : {}

  const app = express()

  /**
   * @type {import('vite').ViteDevServer}
   */
  let vite
  if (!isProd) {
    vite = await require('vite').createServer({
      root,
      logLevel: 'info',
      server: {
        middlewareMode: 'ssr',
        watch: {
          // During tests we edit the files too fast and sometimes chokidar
          // misses change events, so enforce polling for consistency
          usePolling: true,
          interval: 100
        }
      }
    })
    // use vite's connect instance as middleware
    app.use(vite.middlewares)
    app.use(express.json());
    app.use(express.urlencoded({ extended: false }));

    app.use("/api/getSysList", async (req, res) => {
      const data = readFile().map(item => item.sys)
      res.json({
        ...MSG.success,
        data
      });
    });
  
  
    app.use("/api/getJsonData", async (req, res) => {
      const { pageNum: page, pageSize: size, _t, ...rest} = req.query
      let data = readFile(), total = data.length
      let resData
      if (Object.keys(rest).length) {
        resData = filterData(rest, data), total = resData.length;
        resData = resData.splice((page - 1) * size, size)
      } else {
        resData = data.splice((page - 1) * size, size)
      }
     
      res.json({
        ...MSG.success,
        data: resData,
        total
      });
    });
  
    app.use("/api/saveJsonData", async (req, res) => {
      const data = JSON.stringify(req.body);
      // const data = Buffer.from(JSON.stringify(res.body))
      // fs.copyFile('./public/local.json', './local.bak.json', err => {
      //   if (err) console.log('something err.')
      //   else  console.log('copry file success.')
      // })
      // let origin = fs.createReadStream('./public/local.json')
      // let out = fs.createWriteStream('./local.bak.json')
      // origin.pipe(out)
      save(data)
      console.log('save success.')
      res.json(MSG.success);
    });
  
    app.use("/api/delJsonData", async (req, res) => {
      const { id } = req.body
      const bak = readFile()
      bak.splice(bak.findIndex(id => id), 1)
      writeContxt(bak);
      res.json(MSG.success)
    })
  
    app.use("/api/editJsonData", async (req, res) => {
      const { id, _t, ...rest } = req.body
      const bak = readFile()
      let index = bak.findIndex(item => item.id === id)
      bak[index] = { id, ...rest }
      writeContxt(bak);
      res.json(MSG.success)
    })
  
    
  } else {
    app.use(require('compression')())
    app.use(
      require('serve-static')(resolve('dist/client'), {
        index: false
      })
    )
  }
  
  app.use('*', async (req, res) => {
    try {
      const url = req.originalUrl

      let template, render
      if (!isProd) {
        // always read fresh template in dev
        template = fs.readFileSync(resolve('index.html'), 'utf-8')
        template = await vite.transformIndexHtml(url, template)
        render = (await vite.ssrLoadModule('/src/entry-server.js')).render
      } else {
        template = indexProd
        render = require(resolve('./dist/server/entry-server.js')).render
      }

      const [appHtml, preloadLinks] = await render(url, manifest)

      const html = template
        .replace(`<!-- preload-links -->`, preloadLinks)
        .replace(`<!-- app-html-- >`, appHtml)

      res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
    } catch (e) {
      vite && vite.ssrFixStacktrace(e)
      console.log(e.stack)
      res.status(500).end(e.stack)
    }
  })
  

  return { app, vite }
}

  createServer().then(({ app }) =>
    app.listen(port, () => {
      console.log(`http://localhost:${port}`)
    })
  )


// for test use
exports.createServer = createServer


function save(data) {
  data = JSON.parse(data);
  const bak = readFile()
  bak.unshift({id: bak.length + 1, ...data})
  writeContxt(bak)
}

function readFile() {
  return  JSON.parse(fs.readFileSync(resolve(__dirname, JSONFILE), 'utf-8'))
}

function writeContxt(data) {
  const o = JSON.stringify(data)
   // os.EOL 换行符
   fs.writeFileSync(JSONFILE, o + os.EOL);
}

function filterData(field, data) {
  let res = data
  Object.keys(field).forEach((item) => {
    if (field[item]) {
      res = res.filter(f => f[item] == field[item])
    }
  })
  return res;
}